
import java.util.ArrayList;
import java.util.Random;

public class Board {
	public static int DEFAULT_WIDTH = 10;
	public static int DEFAULT_HEIGHT = 20;
	
	private ArrayList<Row> my_blocks;
	private Piece currentPiece;
	private Piece nextPiece;
	private boolean game_over;
	private int score;
	private int level;

	public Board() {
		game_over = false;
		my_blocks = new ArrayList<Row>();
		for (int i = 0; i <= DEFAULT_HEIGHT; i++) {
			my_blocks.add(i, new Row());
		}
		currentPiece = nextPiece();
		nextPiece = nextPiece();
		score = 0;
		level = 1;
	}

	public void nextLevel() {
		if (level <= 10) {
			level++;
		}
	}

	public ArrayList<Block> getBlocks() {
		ArrayList<Block> copy = new ArrayList<Block>();
		for (Row i : my_blocks) {
			for (Block b : i.my_blocks) {
				copy.add(new Block(b.getX(), b.getY(), b.getId()));
			}
		}
		return copy;
	}

	public boolean gameOver() {
		return game_over;
	}

	public Piece nextPiece() {
		Piece nextPiece;
		int center = DEFAULT_WIDTH/2-1;
		Random r = new Random();
		int x = r.nextInt(7);
		if (x == Piece.I_ID - 1) {
			nextPiece = new IPiece(center,0);
		} else if (x == Piece.J_ID - 1) {
			nextPiece = new JPiece(center,0);
		} else if (x == Piece.L_ID - 1) {
			nextPiece = new LPiece(center,0);
		} else if (x == Piece.O_ID - 1) {
			nextPiece = new OPiece(center,0);
		} else if (x == Piece.S_ID - 1) {
			nextPiece = new SPiece(center,0);
		} else if (x == Piece.T_ID - 1) {
			nextPiece = new TPiece(center,0);
		} else {
			nextPiece = new ZPiece(center,0);
		}
		return nextPiece;
	}

	public Piece getCurentPiece() {
		return currentPiece;
	}

	public void update() {
		currentPiece.moveDown();
	}

	public void moveDown() {
		boolean move = true;
		Block c;
		for (Block i : currentPiece.getPiece()) {
			c = new Block(i.getX(), i.getY() + 1, i.getId());
			if (i.getY() >= DEFAULT_HEIGHT) {
				move = false;
				break;
			} else if (my_blocks.get(c.getY()).my_blocks.contains(c)) {
				move = false;
				break;
			}
		}
		if (move == true) {
			currentPiece.moveDown();
		} else {
			addPiece();
			currentPiece = nextPiece;
			nextPiece = nextPiece();
			score(false);
		}
	}
	public int getScore(){
		return score;
	}
	private void score(boolean row){
		if(row){
			score = score+10;
		}else {
			score = score+1;
		}
		
		if(score >= (level*50)){
			nextLevel();
		}
	}
	public void addPiece() {
		for (Block i : currentPiece.getPiece()) {
			if (i.getY() == 0) {
				game_over = true;
			}
			Row c = my_blocks.get(i.getY());
			c.my_blocks.add(i);
		}
		this.clearRows();
	}

	public void moveLeft() {
		boolean move = true;
		Block c;
		for (Block i : currentPiece.getPiece()) {
			c = new Block(i.getX() - 1, i.getY(), i.getId());
			if (my_blocks.get(c.getY()).my_blocks.contains(c)) {
				move = false;
				break;
			} else if (i.getX() <= 0) {
				move = false;
				break;
			}
		}
		if (move == true) {
			currentPiece.moveLeft();
		}

	}

	public void moveRight() {
		boolean move = true;
		Block c;
		for (Block i : currentPiece.getPiece()) {
			c = new Block(i.getX() + 1, i.getY(), i.getId());
			if (my_blocks.get(c.getY()).my_blocks.contains(c)) {
				move = false;
				break;
			} else if (i.getX() >= DEFAULT_WIDTH) {
				move = false;
				break;
			}
		}
		if (move == true) {
			currentPiece.moveRight();
		}
	}

	public void clearRows() {
		ArrayList<Row> full_rows = new ArrayList<Row>();
		for (Row r : my_blocks) {
			if (r.my_blocks.size() == DEFAULT_WIDTH + 1) {
				full_rows.add(r);
			}
		}
		int rn;
		for (Row r : full_rows) {
			rn = my_blocks.indexOf(r);
			my_blocks.remove(r);
			moveDown(rn);
			my_blocks.add(0, new Row());
			score(true);
		}
	}

	private void moveDown(int row) {
		Row r;
		for (int i = 0; i < row; i++) {
			r = my_blocks.get(i);
			for (Block b : r.my_blocks) {
				b.setY(b.getY() + 1);
			}
		}
	}

	public Piece getNextPiece(){
		return nextPiece;
	}
	public void rotate() {
		currentPiece.rotate();
		boolean rotate = true;
		for (Block i : currentPiece.getPiece()) {
			if (my_blocks.get(i.getY()).my_blocks.contains(i)) {
				rotate = false;
				break;
			} else if (i.getX() > DEFAULT_WIDTH) {
				rotate = false;
				break;
			} else if (i.getX() < 0) {
				rotate = false;
				break;
			} else if (i.getY() >= DEFAULT_HEIGHT) {
				rotate = false;
				break;
			} else if (i.getY() < 0) {
				rotate = false;
				break;
			} else {
				rotate = true;
			}
		}
		if (rotate == false) {
			currentPiece.rotate();
			currentPiece.rotate();
			currentPiece.rotate();
		}
	}
	
	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		int board[][] = new int[10][20];
		for(Row r: my_blocks){
			for(Block b:r.my_blocks){
				board[b.getX()][b.getY()] = 1; 
			}
		}
		
		for(Block b : currentPiece.getPiece()){
			board[b.getX()][b.getY()] = 1;
		}
		for(int y = 0; y < board.length;y++){
			for(int x = 0; x < board.length;x++){
				if(board[x][y] == 1){
					sb.append("[]");
				}else{
					sb.append(". ");
				}
			}
			sb.append("\n");
		}
		return sb.toString();
	}
	private class Row {
		private ArrayList<Block> my_blocks;
		
		public Row() {
			my_blocks = new ArrayList<Block>();
		}
	}
	public int getLevel() {
		return level;
	}
}
